﻿using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using Sinacor.Servico.Bovespa.ResumoFinanceiro;
using Sinacor.Servico.Bovespa.Cliente;
using Sinacor.Infra.Common.Exceptions;
using Sinacor.Infra.Service.ExceptionHandling;
using Sinacor.Infra.Service.Security.Authorization;
using Sinacor.Servico.Bovespa.Comum.ResourceAccess;
using Sinacor.Infra.Service.Common;

namespace Sinacor.Servico.Bovespa.ResumoFinanceiro.BusinessLogic
{
    public class ResumoFinanceiro : BaseBusinessLogic
    {
		private const int ERRO_CLIENTENAOENCONTRADO = 104004;// O cliente informado não foi encontrado.
		private const int ERRO_CALCULORESUMOFINANCEIRONAOPERMITIDO = 104005;// Permissão negada para realização do cálculo do resumo financeiro.
		private const int ERRO_NOTANAOALTERADA = 104006;// As informações da nota não foram alteradas.
		private const int ERRO_VALORCORRETAGEMINVALIDO = 104007;// O valor da corretagem deve ser maior do que zero.
		private const int ERRO_VALORTOTALLIQUIDO = 104008;// O valor do total líquido deve ser maior do que zero.
		private const int ERRO_MOVIMENTONAOABERTO = 104009;// O movimento não está aberto.
		private const int ERRO_PERMISSAONEGADAALTERACAOVALORCORRETAGEM = 104010;//Permissão negada para alteração do Valor da Corretagem.
		private const int ERRO_PERMISSAONEGADAALTERACAOTOTALLIQUIDO = 104011;// Permissão negada para alteração do Total Líquido.	
		private const int ERRO_TIPOCLIENTEINVALIDOVALORCORRETAGEM = 104012;// Tipo de cliente informado não tem permissão para alterar o valor da corretagem.
		private const int ERRO_TIPOCLIENTEINVALIDOTOTALLIQUIDO = 104013;// Tipo de cliente informado não tem permissão para alterar o total líquido.
		private const int ERRO_PERCENTUALDESCONTOAPLICADOINVALIDO = 104014;//Percentual de desconto aplicado é inválido.
        private const int ERRO_PERMISSAONEGADAALTERACAOPERCENTUALCORRETAGEM = 104015;
        private const int ERRO_TIPOCLIENTEINVALIDOPERCENTUALCORRETAGEM = 104016;
        private const int ERRO_CLIENTEDESATIVADO = 104017; // Cliente desativado. //incluido - esertorio - 200805021604 - ref issue ID0003694


        /// Data : 12/05/2008
        /// Autor: esertorio
        /// Obs. : CONSTANTES DE ERRO DO SUB-MODULO NEGOCIO - REF ISSUE ID0004618
        private const int ERRO_NEGOCIO_CONTROLE_ORDENS_FECHADO = 103205; //REF ISSUE ID0004618
        private const int ERRO_NEGOCIO_FATURAMENTO_BOLSAS_FECHADO = 103206; //REF ISSUE ID0004618


		/// <summary>
		/// Metodo responsavel por consultar as informacoes de resumo financeiro
		/// </summary>
		/// <param name="modulo">modulo de origiem da solicitacao de execucao</param>
		/// <param name="request"></param>
		/// <returns></returns>
        public List<BusinessEntity.ResumoFinanceiro> ConsultarResumoFinanceiro(BusinessEntity.Enum.ModuloChamador modulo, BusinessEntity.ResumoFinanceiro request)
        {
			//Declarar
			Sinacor.Servico.Bovespa.Cliente.BusinessEntity.Cliente cliente;
            
			ResourceAccess.ResumoFinanceiro raResumoFinanceiro;
			List<BusinessEntity.ResumoFinanceiro> response;

            //Instanciar ResourceAccess
            raResumoFinanceiro = new ResourceAccess.ResumoFinanceiro();

			cliente = (new Sinacor.Servico.Bovespa.Cliente.ResourceAccess.Cliente()).ConsultarPorApelido(request.ApelidoCliente);
			if (cliente == null)
			{
				ValidationException ex = new ValidationException();
				ex.AddError(ERRO_CLIENTENAOENCONTRADO);
				throw ex;
			}
            else if (cliente.Situacao.HasValue && cliente.Situacao.Value == Sinacor.Servico.Bovespa.Cliente.BusinessEntity.Enum.TipoSituacao.Ativo) //incluido - esertorio - 200805021609 - ref issue ID0003694
            {
                request.CodigoCliente = cliente.Codigo.Value;
            }
            else  //incluido - esertorio - 200805021609 - ref issue ID0003694
            {
                ValidationException ex = new ValidationException();
                ex.AddError(ERRO_CLIENTEDESATIVADO); //incluido - esertorio - 200805021609 - ref issue ID0003694
                throw ex;
            }

            //Executar RA
			response = raResumoFinanceiro.Consultar(modulo,request);
			
			///resolver o valor de Iss na corretagem

			if (response != null)
			{
				foreach (BusinessEntity.ResumoFinanceiro item in response)
				{
					item.IndicadorISS = RecuperarDescricaoIndicadorCorretagem(item.IndicadorISS);
				}
			}

            //if (response == null || response.Count == 0)
            //    throw new BusinessException(ERRO_RESUMOFINANCEIRO_PESQUISA_SEM_RESULTADO);

			//Retornar
            return response;
        }

		/// <summary>
		/// Metodo responsavel por recuperar a descricao de um indicador de iss
		/// Data: 14/12/2007
		/// Autor: Diogo Milanez
		/// Obs: Criacao do metodo
		/// </summary>
		/// <param name="indicador"></param>
		/// <returns></returns>
		private string RecuperarDescricaoIndicadorCorretagem(string indicador)
		{
			switch (indicador)
			{
				case "I":
					return "Não desconta o valor de intermediação";
				case "S":
					return "Cobra dentro da corretagem, desconta o custo de intermediação e mostra na nota";
				case "X":
					return "Cobra dentro da corretagem, desconta o custo de intermediação e não mostra na nota ISS";
				case "Z":
					return "Cobra dentro da corretagem, desconta o custo de intermediação, não mostra na nota ISS e intermediação";
				case "Y":
					return "Cobra dentro da corretagem, desconta o custo de intermediação, não mostra na nota intermediação";
				case "L":
					return "Calcula ISS, desconta o custo de intermediação e atualiza o líquido da nota";
				case "N":
					return "Calcula ISS, desconta o custo de intermediação e mostra na nota";
				case "O":
					return "Calcula ISS, desconta o custo de intermediação, não mostra na nota ISS e intermediação";
				case "P":
					return "Calcula ISS, desconta o custo de intermediação, não mostra na nota intermediação";
				default:
					return null;
			}
		}

        public void 
            CalcularResumoFinanceiro(BusinessEntity.ResumoFinanceiro request)
        {
            //Declarar
            ResourceAccess.ResumoFinanceiro raResumoFinanceiro;

            //Validar
            ValidarCalculoResumoFinanceiro(request);

            //Instanciar ResourceAccess
            raResumoFinanceiro = new ResourceAccess.ResumoFinanceiro();

            //Executar            
			raResumoFinanceiro.Calcular(request);
        }

        /// <summary>
        /// Data : 12/05/2008
        /// Autor: Eduardo Sertorio
        /// Obs. : alterado retorno de (void) para (BusinessEntity.RetornoAlteracaoNota) - esertorio - 200805121933 - ref issue ID0004683
        /// Obs. : Incluido parametro (BusinessEntity.Enum.ModuloChamador modulo) para atender chamada (ValidarEstadoSistema) - esertorio - 200805122050 - ref issue ID0004615
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public BusinessEntity.RetornoAlteracaoNota
		   AlterarTotalLiquido(BusinessEntity.ResumoFinanceiro request, BusinessEntity.Enum.ModuloChamador modulo)
        {
			BusinessEntity.RetornoAlteracaoNota response;
			//Declarar
            ResourceAccess.ResumoFinanceiro raResumoFinanceiro;

            //Validar
            ValidarEstadoSistema(modulo); //incluido - eserorio - 200805122041 - ref issue ID0004615
            ValidarAlteracaoTotalLiquido(request);

            //Instanciar ResourceAccess
            raResumoFinanceiro = new ResourceAccess.ResumoFinanceiro();

			request.CodigoUsuario = AuthorizationContext.Current.UserId;
			//Executar
			response = raResumoFinanceiro.AlterarTotalLiquido(request);

            //excluido bloco ini - esertorio - 200805121933 - ref issue ID0004683
            //if (response != null)
            //{
            //    if (!response.AlterouNota)
            //        throw new BusinessException(ERRO_NOTANAOALTERADA);
            //}
            //excluido bloco fim - esertorio - 200805121933 - ref issue ID0004683

            return response; //alterado - esertorio - 200805121933 - ref issue ID0004683
        }

        /// <summary>
        /// Data : 12/05/2008
        /// Autor: Eduardo Sertorio
        /// Obs. : alterado retorno de (void) para (BusinessEntity.RetornoAlteracaoNota) - esertorio - 200805121933 - ref issue ID0004683
        /// Obs. : Incluido parametro (BusinessEntity.Enum.ModuloChamador modulo) para atender chamada (ValidarEstadoSistema) - esertorio - 200805122050 - ref issue ID0004615
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public BusinessEntity.RetornoAlteracaoNota
            AlterarPercentualCorretagem(BusinessEntity.ResumoFinanceiro request, BusinessEntity.Enum.ModuloChamador modulo)
        {
			BusinessEntity.RetornoAlteracaoNota response;
			DateTime dataMovimentoAtual;
			bool existeSistemaOrdens;
            //Declarar
            ResourceAccess.ResumoFinanceiro raResumoFinanceiro;

            ////Validar
            ValidarEstadoSistema(modulo); //incluido - eserorio - 200805122041 - ref issue ID0004615
            ValidarAlteracaoPercentualCorretagem(request);

            ////Instanciar ResourceAccess
            raResumoFinanceiro = new ResourceAccess.ResumoFinanceiro();

            Acesso acesso = new Acesso();

            existeSistemaOrdens = acesso.VerificarSistemaInstalado("ORD");

			///recuperar a data de movimento atual
			dataMovimentoAtual = new Sinacor.Servico.Bovespa.Ordens.ResourceAccess.MovimentoControleOrdens().ConsultarDataMovimento();

            request.CodigoUsuario = AuthorizationContext.Current.UserId;
			
			////Executar
			response = raResumoFinanceiro.AlterarPercentualCorretagem(request, dataMovimentoAtual, existeSistemaOrdens);

            //excluido bloco ini - esertorio - 200805121933 - ref issue ID0004683
            //if (response != null)
            //{
            //    if (!response.AlterouNota)
            //        throw new BusinessException(ERRO_NOTANAOALTERADA);
            //}
            //excluido bloco fim - esertorio - 200805121933 - ref issue ID0004683

            return response; //alterado - esertorio - 200805121933 - ref issue ID0004683
        }

        /// <summary>
        /// Data : 12/05/2008
        /// Autor: Eduardo Sertorio
        /// Obs. : alterado retorno de (void) para (BusinessEntity.RetornoAlteracaoNota) - esertorio - 200805121933 - ref issue ID0004683
        /// Obs. : Incluido parametro (BusinessEntity.Enum.ModuloChamador modulo) para atender chamada (ValidarEstadoSistema) - esertorio - 200805122050 - ref issue ID0004615
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public BusinessEntity.RetornoAlteracaoNota
            AlterarValorCorretagem(BusinessEntity.ResumoFinanceiro request, BusinessEntity.Enum.ModuloChamador modulo)
        {
			BusinessEntity.RetornoAlteracaoNota response;
			//Declarar
			ResourceAccess.ResumoFinanceiro raResumoFinanceiro;

			//Validar
            ValidarEstadoSistema(modulo); //incluido - eserorio - 200805122041 - ref issue ID0004615
            ValidarAlteracaoValorCorretagem(request);

			//Instanciar ResourceAccess
			raResumoFinanceiro = new ResourceAccess.ResumoFinanceiro();

            request.CodigoUsuario = AuthorizationContext.Current.UserId;
			//Executar
			response = raResumoFinanceiro.AlterarValorCorretagem(request);

            //excluido bloco ini - esertorio - 200805121933 - ref issue ID0004683
            //if (response != null)
            //{
            //    if (!response.AlterouNota)
            //        throw new BusinessException(ERRO_NOTANAOALTERADA);
            //}
            //excluido bloco fim - esertorio - 200805121933 - ref issue ID0004683

            return response; //alterado - esertorio - 200805121933 - ref issue ID0004683
        }

        #region Validar

		/// <summary>
		/// Metodo responsavel por validar a execuca do calculo de resumo financeiro
		/// Data: 06/12/2007
		/// Autor: Diogo Milanez
		/// Obs: Criacao do metodo
		/// </summary>
		/// <param name="request"></param>
        private void
			ValidarCalculoResumoFinanceiro(BusinessEntity.ResumoFinanceiro request)
        {
			///se for o resumo financeiro de um correspondente
			///deverar validar se o calculo por ser realizada
			if (request.IsCorrespondente)
			{
				ResourceAccess.Comitente comitenteRA = new ResourceAccess.Comitente();
				BusinessEntity.Comitente comitenteBE = new BusinessEntity.Comitente();
				comitenteBE.CodigoCliente = request.CodigoCliente;
				comitenteBE.DataMovimento = request.DataMovimento;

				if (!comitenteRA.VerificarPermissaoExecucaoCalculoFinanceiroCorrespondente(comitenteBE))
				{
					throw new BusinessException(ERRO_CALCULORESUMOFINANCEIRONAOPERMITIDO);
				}
			}
        }

        private void
			ValidarAlteracaoTotalLiquido(BusinessEntity.ResumoFinanceiro request)
        {

            //codigo movido do fim para inicio do metodo - esertorio - 200805122015 - ref issue ID0004726
            ///O usuário deve possuir acesso à função 'ACOR'
            if (!Sinacor.Servico.Bovespa.Comum.ResourceAccess.Acesso.VerificarAcessoFuncao("ATOT")) //corrigido de (ACOR) para (ATOT) - esertorio - 200805122007 - ref issue ID0004726
                throw new BusinessException(ERRO_PERMISSAONEGADAALTERACAOTOTALLIQUIDO);

            if (request.TipoCliente != Sinacor.Servico.Bovespa.ResumoFinanceiro.BusinessEntity.Enum.TipoCliente.Cliente)
			{
				throw new BusinessException(ERRO_TIPOCLIENTEINVALIDOTOTALLIQUIDO);
			}

            ////O valor de corretagem proposto não deve ser menor que zero 
            //if (request.ValorLiquidoNotaCorretagem < Decimal.Zero)
            //    throw new BusinessException(ERRO_VALORTOTALLIQUIDO);

			//O movimento de Controle de Ordens Bovespa deve estar aberto ( TORDATMOV.TP_MOVIMENTO = 'A' )
			//OU O módulo de Faturamento de Bolsas Bovespa deve estar aberto ( TBOPARAM.TP_MOVIMENTO = 'A' )
            Parametros parametros = new Parametros();

			if (new Sinacor.Servico.Bovespa.Ordens.ResourceAccess.MovimentoControleOrdens().ConsultarTipoMovimento() != "A" &&
				parametros.ConsultarTipoMovimento() != "A")
				throw new BusinessException(ERRO_MOVIMENTONAOABERTO);	
        }

		/// <summary>
		/// Metodo responsavel por verificar a permissao de execucao da alteracao do valor de corretagem
		/// </summary>
		/// <param name="request"></param>
        private void
			ValidarAlteracaoValorCorretagem(BusinessEntity.ResumoFinanceiro request)
        {
            //codigo movido do fim para inicio do metodo - esertorio - 200805122015 - ref issue ID0004726
            ///O usuário deve possuir acesso à função 'ACOR'
            if (!Sinacor.Servico.Bovespa.Comum.ResourceAccess.Acesso.VerificarAcessoFuncao("ACOR"))
                throw new BusinessException(ERRO_PERMISSAONEGADAALTERACAOVALORCORRETAGEM);

            if (request.TipoCliente != Sinacor.Servico.Bovespa.ResumoFinanceiro.BusinessEntity.Enum.TipoCliente.Cliente)
			{
				throw new BusinessException(ERRO_TIPOCLIENTEINVALIDOVALORCORRETAGEM);
			}

			//O valor de corretagem proposto não deve ser menor que zero 
			if (request.ValorCorretagem < Decimal.Zero)
				throw new BusinessException(ERRO_VALORCORRETAGEMINVALIDO);

			//O movimento de Controle de Ordens Bovespa deve estar aberto ( TORDATMOV.TP_MOVIMENTO = 'A' )
			//OU O módulo de Faturamento de Bolsas Bovespa deve estar aberto ( TBOPARAM.TP_MOVIMENTO = 'A' )

            Parametros parametros = new Parametros();
            if (new Sinacor.Servico.Bovespa.Ordens.ResourceAccess.MovimentoControleOrdens().ConsultarTipoMovimento() != "A" &&
                parametros.ConsultarTipoMovimento() != "A")
				throw new BusinessException(ERRO_MOVIMENTONAOABERTO);

        }

        /// <summary>
        /// Metodo responsavel por validar o percentual de reducao/acrescrimo (corretagem)
        /// Data: 06/12/2007
        /// Autor: Diogo Milanez
        /// Obs: Criacao do metodo
        /// 
        /// Autor: Eduardo Sertorio
        /// Data : 19/12/2007
        /// Obs. : alterada visibilidade do  metodo de [private] para [public] para reaproveitar funcao no servico Ordem(OrdemMegaBolsa)
        /// </summary>
        /// <param name="request"></param>
        public void
			ValidarAlteracaoPercentualCorretagem(BusinessEntity.ResumoFinanceiro request)
        {
            decimal percentualCustoTotalVolume;
            Sinacor.Servico.Bovespa.Cliente.BusinessEntity.Cliente cliente = new Sinacor.Servico.Bovespa.Cliente.BusinessEntity.Cliente();

            //codigo movido do fim para inicio do metodo - esertorio - 200805122015 - ref issue ID0004726
            ///O usuário deve possuir acesso à função 'ACOR'
            if (!Sinacor.Servico.Bovespa.Comum.ResourceAccess.Acesso.VerificarAcessoFuncao("ACOR"))
                throw new BusinessException(ERRO_PERMISSAONEGADAALTERACAOPERCENTUALCORRETAGEM);

			if (request.TipoCliente != Sinacor.Servico.Bovespa.ResumoFinanceiro.BusinessEntity.Enum.TipoCliente.Cliente)
			{
                throw new BusinessException(ERRO_TIPOCLIENTEINVALIDOPERCENTUALCORRETAGEM);
			}

			cliente.Codigo = request.CodigoCliente;
			percentualCustoTotalVolume = (new Sinacor.Servico.Bovespa.Cliente.ResourceAccess.Cliente()).ConsultarPercentualCustoTotalVolume(cliente);

			if (percentualCustoTotalVolume == 0)
			{
				if (request.PorcentagemDescontoAplicado < -100)
					throw new BusinessException(ERRO_PERCENTUALDESCONTOAPLICADOINVALIDO);
			}
			else if (percentualCustoTotalVolume >= 0)
			{
				if (request.PorcentagemDescontoAplicado < 0)
					throw new BusinessException(ERRO_PERCENTUALDESCONTOAPLICADOINVALIDO);
			}

			//O movimento de Controle de Ordens Bovespa deve estar aberto ( TORDATMOV.TP_MOVIMENTO = 'A' )
			//OU O módulo de Faturamento de Bolsas Bovespa deve estar aberto ( TBOPARAM.TP_MOVIMENTO = 'A' )
            Parametros parametros = new Parametros();
            if (new Sinacor.Servico.Bovespa.Ordens.ResourceAccess.MovimentoControleOrdens().ConsultarTipoMovimento() != "A" &&
                parametros.ConsultarTipoMovimento() != "A")
				throw new BusinessException(ERRO_MOVIMENTONAOABERTO);	

        }

        #endregion


        /// Data:12/05/2008 14:30
        /// Autor:Rvaladao
        /// Obs: Validar o estado do sistema
        /// Issue 4618
        public void ValidarEstadoSistema(BusinessEntity.Enum.ModuloChamador modulo)
        {
            string strTipoMovimento = string.Empty;
            int iCodErro = 0;
            if (modulo == BusinessEntity.Enum.ModuloChamador.FaturamentoBolsas)
            {
                Acesso acesso = new Acesso();
                if (acesso.VerificarSistemaInstalado("ORD"))
                {
                    strTipoMovimento = new Sinacor.Servico.Bovespa.Ordens.ResourceAccess.MovimentoControleOrdens().ConsultarTipoMovimento();
                    iCodErro = ERRO_NEGOCIO_CONTROLE_ORDENS_FECHADO;
                }
                else
                {
                    Parametros parametros = new Parametros();
                    strTipoMovimento = parametros.ConsultarTipoMovimento();
                    iCodErro = ERRO_NEGOCIO_FATURAMENTO_BOLSAS_FECHADO;
                }
            }
            else //se for ModuloChamador.ControleOrdens
            {

                strTipoMovimento = new Sinacor.Servico.Bovespa.Ordens.ResourceAccess.MovimentoControleOrdens().ConsultarTipoMovimento();
                iCodErro = ERRO_NEGOCIO_CONTROLE_ORDENS_FECHADO;
            }

            if (!strTipoMovimento.Equals("A"))
            {
                throw new BusinessException(iCodErro);
            }
        }
    }
}
